#include "tusb564.h"

/**
 * @brief 从TUSB564寄存器读取数据
 * 
 * @param slave_addr 寄存器地址
 * @return uint8_t 
 */
uint8_t tusb564_reg_read(uint8_t slave_addr){
    uint8_t val;
    IIC_ReadSlave(TUSB564_I2C_SLAVE_ADDR, slave_addr & 0xFF, &val, 1);
    return val;
}

/**
 * @brief 往TUSB564寄存器写数据
 * 
 * @param slave_addr 寄存器地址
 * @param data 
 */
void tusb564_reg_write(uint8_t slave_addr, uint8_t val){
    uint8_t data[] = {slave_addr & 0xFF, val & 0xFF};
    IIC_WriteSlave(TUSB564_I2C_SLAVE_ADDR, data, 2);
}

/**
 * @brief 设置EQ由谁来控制（默认由引脚控制）
 *      TRUE 由引脚控制
 *      FALSE 由寄存器控制
 * 
 * @param from_pin 
 */
void tusb564_EQ(bool from_pin){
    uint8_t reg = tusb564_reg_read(MUX_REG_GENERAL);
    if (from_pin)
    {
        reg &= ~MUX_REG_GENERAL_EQ_OVERRIDE;
    }else {
        reg |= MUX_REG_GENERAL_EQ_OVERRIDE;
    }
    tusb564_reg_write(MUX_REG_GENERAL, reg);
}

/**
 * @brief 设置DP由谁来控制（默认由寄存器控制）
 *      TRUE 由引脚控制
 *      FALSE 由寄存器控制
 * 
 * @param from_pin 
 */
void tusb564_DP_EN(bool from_pin){
    uint8_t reg = tusb564_reg_read(MUX_REG_GENERAL);
    if (from_pin)
    {
        reg |= MUX_REG_GENERAL_DP_EN_CTRL;
    }else {
        reg &= ~MUX_REG_GENERAL_DP_EN_CTRL;
    }
    tusb564_reg_write(MUX_REG_GENERAL, reg);
}

/**
 * @brief 是否引脚反转（默认不反转）
 * 
 * @param flip 
 */
void tusb564_FLIP(bool flip){
    uint8_t reg = tusb564_reg_read(MUX_REG_GENERAL);
    if (flip)
    {
        reg |= MUX_REG_GENERAL_FLIPSEL;
    }else {
        reg &= ~MUX_REG_GENERAL_FLIPSEL;
    }
    tusb564_reg_write(MUX_REG_GENERAL, reg);
}

/**
 * @brief 设置模式（默认USB3_Only）
 * 
 * @param ctl 
 */
void tusb564_CTLSEL(ctlsel ctl){
    uint8_t reg = tusb564_reg_read(MUX_REG_GENERAL);
    reg &= ~MUX_REG_GENERAL_CTLSEL;         //清除对应位置的值
    reg |= ctl;
    tusb564_reg_write(MUX_REG_GENERAL, reg);
}

/**
 * @brief 设置DP0通道的增益（默认-0.3）
 * 
 * @param db 
 */
void tusb564_DP0EQ(dp_lane_dB db){
    uint8_t reg = tusb564_reg_read(MUX_REG_DP_CONTROLB);
    reg &= ~MUX_REG_DP_CONTROLB_DP0EQ_SEL;         //清除对应位置的值
    reg |= db << 4;
    tusb564_reg_write(MUX_REG_DP_CONTROLB, reg);
}

/**
 * @brief 设置DP1通道的增益（默认-0.3）
 * 
 * @param db 
 */
void tusb564_DP1EQ(dp_lane_dB db){
    uint8_t reg = tusb564_reg_read(MUX_REG_DP_CONTROLA);
    reg &= ~MUX_REG_DP_CONTROLA_DP1EQ_SEL;         //清除对应位置的值
    reg |= db << 4;
    tusb564_reg_write(MUX_REG_DP_CONTROLA, reg);
}

/**
 * @brief 设置DP2通道的增益（默认-0.3）
 * 
 * @param db 
 */
void tusb564_DP2EQ(dp_lane_dB db){
    uint8_t reg = tusb564_reg_read(MUX_REG_DP_CONTROLB);
    reg &= ~MUX_REG_DP_CONTROLB_DP2EQ_SEL;         //清除对应位置的值
    reg |= db;
    tusb564_reg_write(MUX_REG_DP_CONTROLB, reg);
}

/**
 * @brief 设置DP3通道的增益（默认-0.3）
 * 
 * @param db 
 */
void tusb564_DP3EQ(dp_lane_dB db){
    uint8_t reg = tusb564_reg_read(MUX_REG_DP_CONTROLA);
    reg &= ~MUX_REG_DP_CONTROLA_DP3EQ_SEL;         //清除对应位置的值
    reg |= db;
    tusb564_reg_write(MUX_REG_DP_CONTROLA, reg);
}

/**
 * @brief 监听AUX写到DPCD地址0x00600的值。
 *      当AUX_SNOOP_DISABLE值为0时，TUSB564将根据此值启用DP通道
 *      当AUX_SNOOP_DISABLE值为1时，TUSB564将根据DPx_DISABLE寄存器的设置禁用DP通道
 *      当CTLSEL1修改后此值将会被硬件重置为0x0
 * @return uint8_t 
 */
uint8_t tusb564_Power_State(void){
    uint8_t reg = tusb564_reg_read(MUX_REG_DP_CONTROLC);
    reg &= MUX_REG_DP_CONTROLC_SET_POWER_STATE;
    return reg >> 5;
}

/**
 * @brief 监听AUX写到DPCD地址0x00101的值。
 *      当AUX_SNOOP_DISABLE值为0时，TUSB564将根据此值启用DP通道，未使用的通道将会为了省电被禁用
 *      当AUX_SNOOP_DISABLE值为1时，TUSB564将根据DPx_DISABLE寄存器的设置禁用DP通道
 *      当CTLSEL1修改后此值将会被硬件重置为0x0
 * @return uint8_t 
 */
uint8_t tusb564_Line_Count(void){
    uint8_t reg = tusb564_reg_read(MUX_REG_DP_CONTROLC);
    reg &= MUX_REG_DP_CONTROLC_LANE_COUNT_SET;
    return reg;
}

/**
 * @brief 是否启用AUX监听（默认启用）
 * 
 * @param enable 
 * @return uint8_t 
 */
void tusb564_AUX_SNOOP(bool enable){
    uint8_t reg = tusb564_reg_read(MUX_REG_DP_CONTROLD);
    if (enable)
    {
        reg &= ~MUX_REG_DP_CONTROLD_AUX_SNOOP_DISABLE;
    }else {
        reg |= MUX_REG_DP_CONTROLD_AUX_SNOOP_DISABLE;
    }
    tusb564_reg_write(MUX_REG_DP_CONTROLD, reg);
}

/**
 * @brief 设置AUX与SBU的连接方式（默认由CTLSEL1和FLIPSEL决定）
 * 
 * @param ovr 
 */
void tusb564_AUX_SBU_OVR(aux_sbu_ovr ovr){
    uint8_t reg = tusb564_reg_read(MUX_REG_DP_CONTROLD);
    reg &= ~MUX_REG_DP_CONTROLD_AUX_SBU_OVR;        //清除对应位置的值
    reg |= ovr << 4;
    tusb564_reg_write(MUX_REG_DP_CONTROLD, reg);
}

/**
 * @brief 是否启用DP0通道（默认启用）
 * 
 * @param enable 
 */
void tusb564_DP0(bool enable){
    uint8_t reg = tusb564_reg_read(MUX_REG_DP_CONTROLD);
    if (enable)
    {
        reg &= ~MUX_REG_DP_CONTROLD_DP0_DISABLE;
    }else {
        reg |= MUX_REG_DP_CONTROLD_DP0_DISABLE;
    }
    tusb564_reg_write(MUX_REG_DP_CONTROLD, reg);
}

/**
 * @brief 是否启用DP1通道（默认启用）
 * 
 * @param enable 
 */
void tusb564_DP1(bool enable){
    uint8_t reg = tusb564_reg_read(MUX_REG_DP_CONTROLD);
    if (enable)
    {
        reg &= ~MUX_REG_DP_CONTROLD_DP1_DISABLE;
    }else {
        reg |= MUX_REG_DP_CONTROLD_DP1_DISABLE;
    }
    tusb564_reg_write(MUX_REG_DP_CONTROLD, reg);
}

/**
 * @brief 是否启用DP2通道（默认启用）
 * 
 * @param enable 
 */
void tusb564_DP2(bool enable){
    uint8_t reg = tusb564_reg_read(MUX_REG_DP_CONTROLD);
    if (enable)
    {
        reg &= ~MUX_REG_DP_CONTROLD_DP2_DISABLE;
    }else {
        reg |= MUX_REG_DP_CONTROLD_DP2_DISABLE;
    }
    tusb564_reg_write(MUX_REG_DP_CONTROLD, reg);
}

/**
 * @brief 是否启用DP3通道（默认启用）
 * 
 * @param enable 
 */
void tusb564_DP3(bool enable){
    uint8_t reg = tusb564_reg_read(MUX_REG_DP_CONTROLD);
    if (enable)
    {
        reg &= ~MUX_REG_DP_CONTROLD_DP3_DISABLE;
    }else {
        reg |= MUX_REG_DP_CONTROLD_DP3_DISABLE;
    }
    tusb564_reg_write(MUX_REG_DP_CONTROLD, reg);
}

/**
 * @brief 设置USB3 RX1接收的增益（默认-0.9）
 * 
 * @param db 
 */
void tusb564_USB3_EQ1(usb3_ufp_dB db){
    uint8_t reg = tusb564_reg_read(MUX_REG_USB3_1_CONTROLA);
    reg &= ~MUX_REG_USB3_1_CONTROLA_EQ1_SEL;        //清除对应位置的值
    reg |= db;
    tusb564_reg_write(MUX_REG_USB3_1_CONTROLA, reg);
}

/**
 * @brief 设置USB3 RX2接收的增益（默认-0.9）
 * 
 * @param db 
 */
void tusb564_USB3_EQ2(usb3_ufp_dB db){
    uint8_t reg = tusb564_reg_read(MUX_REG_USB3_1_CONTROLA);
    reg &= ~MUX_REG_USB3_1_CONTROLA_EQ2_SEL;        //清除对应位置的值
    reg |= db << 4;
    tusb564_reg_write(MUX_REG_USB3_1_CONTROLA, reg);
}

/**
 * @brief 设置USB3 SSTX接收的增益（默认-2.4）
 * 
 * @param db 
 */
void tusb564_USB3_SSEQ(usb3_dfp_dB db){
    tusb564_reg_write(MUX_REG_USB3_1_CONTROLB, db);
}

/**
 * @brief 查看设备是否在USB3.1兼容模式（默认不在）
 * 
 * @return true 
 * @return false 
 */
bool tusb564_CM_Active(void){
    uint8_t reg = tusb564_reg_read(MUX_REG_USB3_1_CONTROLC);
    if(reg & MUX_REG_USB3_1_CONTROLC_CM_ACTIVE)
        return TRUE;
    else
        return FALSE;
}

/**
 * @brief 接收到LFPS信号后基于EQ1_SEL、EQ2_SEL和SSEQ_SEL的EQ设置是否还适用。（默认会清零）
 *      TRUE 接收到LFPS信号后EQ的设置还是基于EQ1_SEL、EQ2_SEL和SSEQ_SEL
 *      FALSE 接收到LFPS信号后EQ的设置清零
 * @param from_LFPS 
 */
void tusb564_LFPS_EQ(bool apply){
    uint8_t reg = tusb564_reg_read(MUX_REG_USB3_1_CONTROLC);
    if (apply)
    {
        reg |= MUX_REG_USB3_1_CONTROLC_LFPS_EQ;
    }else {
        reg &= ~MUX_REG_USB3_1_CONTROLC_LFPS_EQ;
    }
    tusb564_reg_write(MUX_REG_USB3_1_CONTROLC, reg);
}

/**
 * @brief 设置在U2/U3退出之前有没有防抖动（默认没有）
 *      TRUE 在U2/U3退出之前有200us的LFPS防抖动
 *      FALSE 在U2/U3退出之前没有LFPS的防抖动
 * 
 * @param debounce 
 */
void tusb564_U2U3_LFPS_DEBOUNCE(bool debounce){
    uint8_t reg = tusb564_reg_read(MUX_REG_USB3_1_CONTROLC);
    if (debounce)
    {
        reg |= MUX_REG_USB3_1_CONTROLC_U2U3_LFPS_DEBOUNCE;
    }else {
        reg &= ~MUX_REG_USB3_1_CONTROLC_U2U3_LFPS_DEBOUNCE;
    }
    tusb564_reg_write(MUX_REG_USB3_1_CONTROLC, reg);
}

/**
 * @brief 是否启用U2/U3的Rx.Detect阶段（默认启用）
 * 
 * @param enable 
 */
void tusb564_U2U3_RXDET(bool enable){
    uint8_t reg = tusb564_reg_read(MUX_REG_USB3_1_CONTROLC);
    if (enable)
    {
        reg &= ~MUX_REG_USB3_1_CONTROLC_DISABLE_U2U3_RXDET;
    }else {
        reg |= MUX_REG_USB3_1_CONTROLC_DISABLE_U2U3_RXDET;
    }
    tusb564_reg_write(MUX_REG_USB3_1_CONTROLC, reg);
}

/**
 * @brief 设置DFP的Rx.Detect时间间隔（默认12ms）
 * 
 * @param rxdet 
 */
void tusb564_DFP_RXDET_INTERVAL(dfp_rxdet_interval rxdet){
    uint8_t reg = tusb564_reg_read(MUX_REG_USB3_1_CONTROLC);
    reg &= ~MUX_REG_USB3_1_CONTROLC_DFP_RXDET_INTERVAL; //清除对应位置的值
    reg |= rxdet << 2;
    tusb564_reg_write(MUX_REG_USB3_1_CONTROLC, reg);
}

/**
 * @brief 设置USB3的兼容模式（默认由FSM决定）
 * 
 * @param mode 
 */
void tusb564_USB3_COMPLIANCE(usb3_compliance_mode mode){
    uint8_t reg = tusb564_reg_read(MUX_REG_USB3_1_CONTROLC);
    reg &= ~MUX_REG_USB3_1_CONTROLC_USB3_COMPLIANCE_CTRL; //清除对应位置的值
    reg |= mode;
    tusb564_reg_write(MUX_REG_USB3_1_CONTROLC, reg);
}
